package com.spzx.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.spzx.product.api.domain.ProductSku;
import com.spzx.product.domain.Product;
import com.spzx.product.domain.ProductDetails;
import com.spzx.product.domain.SkuStock;
import com.spzx.product.mapper.ProductDetailsMapper;
import com.spzx.product.mapper.ProductMapper;
import com.spzx.product.mapper.ProductSkuMapper;
import com.spzx.product.mapper.SkuStockMapper;
import com.spzx.product.service.IProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 商品 服务实现类
 * </p>
 *
 * @author atguigu
 * @since 2024-12-19
 */
@Service
public class ProductServiceImpl extends ServiceImpl<ProductMapper, Product> implements IProductService {

    @Override
    public List<Product> selectProductList() {
        return baseMapper.selectProductList();
    }

    @Autowired
    private ProductSkuMapper productSkuMapper;

    @Autowired
    private ProductDetailsMapper productDetailsMapper;

    @Autowired
    private SkuStockMapper skuStockMapper;

    @Transactional(rollbackFor = Exception.class)
    @Override
    public int insertProduct(Product product) {
        baseMapper.insert(product);

        List<ProductSku> productSkuList = product.getProductSkuList();
        for (int i = 0, size = productSkuList.size(); i < size; i++) {
            ProductSku productSku = productSkuList.get(i);
            productSku.setSkuCode(product.getId() + "_" + i);
            productSku.setProductId(product.getId());
            String skuName = product.getName() + " " + productSku.getSkuSpec();
            productSku.setSkuName(skuName);
            productSku.setStatus((byte) 0);
            productSkuMapper.insert(productSku);

            //添加商品库存
            SkuStock skuStock = new SkuStock();
            skuStock.setSkuId(productSku.getId());
            skuStock.setTotalNum(productSku.getStockNum());
            skuStock.setLockNum(0);
            skuStock.setAvailableNum(productSku.getStockNum());
            skuStock.setSaleNum(0);
            skuStockMapper.insert(skuStock);
        }

        ProductDetails productDetails = new ProductDetails();
        productDetails.setProductId(product.getId());
        productDetails.setImageUrls(String.join(",", product.getDetailsImageUrlList()));
        productDetailsMapper.insert(productDetails);

        return 1;
    }


    @Autowired
    private StringRedisTemplate redisTemplate;

    /**
     * 更新产品的状态，并同步更新与该产品关联的所有库存单位（SKU）的状态。
     *
     * @param id   产品ID，用于标识要更新的产品。
     * @param status  新的产品状态，1表示上架，-1表示下架。其他值可能会导致未定义行为。
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateStatus(Long id, Byte status) {
        // 创建Product对象并设置ID和状态，用于更新产品状态
        Product product = new Product();
        product.setId(id);
        product.setStatus(status);

        // 使用MyBatis-Plus的baseMapper根据产品ID更新产品状态
        baseMapper.updateById(product);

        // 更新与产品关联的所有SKU的状态为与产品相同的状态
        productSkuMapper.update(
                null,
                new LambdaUpdateWrapper<ProductSku>()
                        .eq(ProductSku::getProductId, id)
                        .set(ProductSku::getStatus, status));

        // 定义Redis中的键，用于存储SKU数据
        String key = "product:sku:data";

        // 根据产品ID查询所有与该产品关联的SKU列表
        List<ProductSku> productSkus = productSkuMapper.selectList(
                new LambdaQueryWrapper<ProductSku>()
                        .eq(ProductSku::getProductId, id));

        // 根据产品状态更新Redis中对应SKU的状态位
        if (status == 1) {
            // 如果产品状态为上架，则将每个SKU在Redis中的对应位置设置为true（1）
            productSkus.forEach(
                    productSku ->
                            redisTemplate.opsForValue().setBit(key, productSku.getId(), true)
            );
        } else if (status == -1) {
            // 如果产品状态为下架，则将每个SKU在Redis中的对应位置设置为false（0）
            productSkus.forEach(
                    productSku ->
                            redisTemplate.opsForValue().setBit(key, productSku.getId(), false)
            );
        }
    }


    /**
     * 通过商品ID列表删除商品及其相关数据
     * 此方法使用事务管理，确保数据一致性
     * 当操作失败时，会回滚所有更改
     *
     * @param ids 商品ID列表
     * @return 删除的商品库存记录数
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public int deleteProductByIds(List<Long> ids) {

        // 删除商品
        baseMapper.deleteBatchIds(ids);

        //查询skuIds(先查询)

        List<ProductSku> productSkuList = productSkuMapper
                .selectList(
                        new LambdaQueryWrapper<ProductSku>()
                        .in(ProductSku::getProductId, ids)
                        .select(ProductSku::getId)
                );

        List<Long> skuIds = productSkuList
                .stream()
                .map(ProductSku::getId)
                .collect(Collectors.toList());

        // 删除商品sku（再删除）
        productSkuMapper.delete(
                new LambdaQueryWrapper<ProductSku>()
                        .in(ProductSku::getProductId, ids)
        );

        //删除商品详情
        productDetailsMapper.delete(
                new LambdaQueryWrapper<ProductDetails>()
                        .in(ProductDetails::getProductId, ids)
        );

        //删除商品库存
        if (!skuIds.isEmpty()) {
            // 删除商品库存
            return skuStockMapper.delete(
                    new LambdaQueryWrapper<SkuStock>()
                            .in(SkuStock::getSkuId, skuIds)
            );
        } else {
            // 如果没有 skuIds，返回 0 或者其他合适的值
            return 0;
        }
    }
}
